package university;

import university.exceptions.CannotAddToListException;

import java.io.*;
import java.util.*;

/**
 * Created by anatolii.bondarenko on 2/12/14.
 */
class Schedule {
    private List<AuditoriumClass> auditoriumClasses;
    public Schedule(){
        auditoriumClasses = new ArrayList<AuditoriumClass>(0);
    }

    public void addLessonToSchedule(AuditoriumClass auditoriumClass) throws CannotAddToListException{
        for (AuditoriumClass i : auditoriumClasses){
            if (i == null){
                break;
            }
            else if (i.getTimeAndPlace().getDayOfWeek()==auditoriumClass.getTimeAndPlace().getDayOfWeek()){
                if(i.getTimeAndPlace().getLessonNumber()==auditoriumClass.getTimeAndPlace().getLessonNumber()){
                    //at the same day and same time one teacher cannot be at two different classes
                    if(i.getDiscipline().getTeacher().equals(auditoriumClass.getDiscipline().getTeacher())){
                        throw new CannotAddToListException("At the same day and same time one teacher cannot be at two different classes");
                    }
                    //at the same day and same time one room cannot be given for two different classes
                    if (i.getTimeAndPlace().getBuilding()==auditoriumClass.getTimeAndPlace().getBuilding() && i.getTimeAndPlace().getRoom()==auditoriumClass.getTimeAndPlace().getRoom()){
                        throw new CannotAddToListException("At the same day and same time one room cannot be given for two different classes");
                    }
                    //one group cannot be at two classes at the same time
                    if (i.getGroup().equals(auditoriumClass.getGroup())){
                        throw new CannotAddToListException("One group cannot be at two classes at the same time");
                    }
                }
            }
        }
            auditoriumClasses.add(auditoriumClass);
        }

    public List<AuditoriumClass> getAuditoriumClasses(){
        return auditoriumClasses;
    }

    public String getScheduleForGroup(Group group){
        //get classes of specified group from common list of classes
        List<AuditoriumClass> scheduleForGroup = new ArrayList<AuditoriumClass>(0);

        for (AuditoriumClass a:auditoriumClasses){
            if (a.getGroup().equals(group)){
                scheduleForGroup.add(a);
            }
        }

        String s = "Schedule for group " + group.getGroupName() + ":\n";
        for(int i = Calendar.MONDAY; i<= Calendar.SATURDAY; i++){
            if (i == Calendar.MONDAY){
                    s = s + "Monday:\n";
                }
            else if(i == Calendar.TUESDAY){
                    s = s + "Tuesday:\n";
                }
            else if(i == Calendar.WEDNESDAY){
                    s = s + "Wednesday:\n";
                }
            else if(i == Calendar.THURSDAY){
                    s = s + "Thursday:\n";
                }
            else if(i == Calendar.FRIDAY){
                    s = s + "Friday:\n";
                }
            else if(i == Calendar.SATURDAY){
                    s = s + "Saturday:\n";
                }
            for(int j = 1; j <= 6; j++){
                s = s + j + ". ";
                for (AuditoriumClass ac:scheduleForGroup){
                    if(ac.getTimeAndPlace().getLessonNumber()==j && ac.getTimeAndPlace().getDayOfWeek()==i){
                        s = s + ac.toString();
                    }
                }
                s = s + "\n";
            }
        }
        return s;
    }


    public boolean isScheduleValid(){
        List<Discipline> disciplinesInSchedule= new ArrayList<Discipline>(0);
        boolean isValid = true;
        //creates list of all disciplines available in schedule
        for (AuditoriumClass ac:auditoriumClasses){
            if(!disciplinesInSchedule.contains(ac.getDiscipline())){
                disciplinesInSchedule.add(ac.getDiscipline());
            }
        }

        for (Discipline d: disciplinesInSchedule){
            int lectures = 0;
            int practices = 0;
            for (AuditoriumClass ac:auditoriumClasses){
                if (d.equals(ac.getDiscipline())){
                    if(ac instanceof Lecture){
                        lectures++;
                    }
                    if(ac instanceof PracticalClass){
                        practices++;
                    }
                }
            }
            if (lectures > 0 && practices > 0){
                isValid = true;
            }
            else {
                isValid = false;
                break;
            }
        }

    return isValid;
    }
    public List<AuditoriumClass> getSchedule(){
        return auditoriumClasses;
    }

    public static void main(String[] args) throws Exception{
        File buildings = new File("buildings.dat");
        File disciplines = new File("disciplines.dat");
        File groups = new File("groups.dat");
        File groupList = new File("groupList.dat");
        File rooms = new File("rooms.dat");
        File teachers = new File("teachers.dat");

        Schedule schedule = new Schedule();
        Scanner in = new Scanner(System.in);

        List<Group> groupsList = null;
        try {
            FileInputStream fis = new FileInputStream("groupsList.dat");
            ObjectInputStream ois =new ObjectInputStream(fis);
            groupsList = (List<Group>) ois.readObject();
            ois.close();
        }
        catch (Exception e){}

        //build schedule
        String finishSchedule;
        do{
            int dayOfWeek = 0;
            int lessonNumber = 0;
            Integer building = 0;
            Integer room = 0;
            Discipline discipline = null;
            Group group = null;

            //select day of week for new class in schedule
            while(dayOfWeek<2 || dayOfWeek>7) {
                System.out.println("Please Select day of week(from 2 to 7)");
                dayOfWeek = in.nextInt();
                in.nextLine();
                if (dayOfWeek<2 || dayOfWeek>7){
                    System.out.println("Invalid Day of week. Please try again");
                }
            }

            //select lesson number for new class in schedule
            while(lessonNumber<1 || lessonNumber>6){
                System.out.println("Please select Lesson Number(from 1 to 6)");
                lessonNumber = in.nextInt();
                in.nextLine();
                if (lessonNumber<1 || lessonNumber>6){
                    System.out.println("Invalid lesson number. Please try again");
                }
            }

            //select building from available buildings in file buildings.dat
            boolean validBuilding;
            do{
                validBuilding = false;
                System.out.println("Please select building for the lesson from following list:");
                FileReader fr = new FileReader(buildings);
                BufferedReader br = new BufferedReader(fr);
                br.mark(100);
                String s;
                while ((s = br.readLine()) != null){
                    System.out.println(s);
                }
                br.reset();
                building = in.nextInt();
                in.nextLine();
                while ((s = br.readLine()) != null){
                    if (s.equals(building.toString())){
                        validBuilding = true;
                    }
                }
                if (!validBuilding){
                    System.out.println("Invalid choice. Please try again.");
                }
            }while(!validBuilding);

            //select room from available rooms in file rooms.dat
            boolean validRoom;
            do{
                validRoom = false;
                System.out.println("Please select room for the lesson from following list:");
                FileReader fr = new FileReader(rooms);
                BufferedReader br = new BufferedReader(fr);
                br.mark(65535);
                String s;
                while ((s = br.readLine()) != null){
                    System.out.println(s);
                }
                br.reset();
                room = in.nextInt();
                in.nextLine();
                while ((s = br.readLine()) != null){
                    if (s.equals(room.toString())){
                        validRoom = true;
                    }
                }
                if (!validRoom){
                    System.out.println("Invalid choice. Please try again.");
                }
            }while(!validRoom);

            //select discipline and teacher from file teachers.dat
            boolean validDiscipline;
            do{
                validDiscipline = false;
                System.out.println("Please select discipline and teacher for the lesson from following list:");
                FileReader fr = new FileReader(teachers);
                BufferedReader br = new BufferedReader(fr);

                String s;
                while ((s = br.readLine()) != null){
                    System.out.println(s);
                }
                System.out.println("Select Teacher");
                String teacher = in.nextLine();
                System.out.println("Select Discipline");
                String disciplineName = in.nextLine();

                List<Discipline> disciplineList = null;
                try {
                    FileInputStream fis = new FileInputStream("disciplines.dat");
                    ObjectInputStream ois =new ObjectInputStream(fis);
                    disciplineList = (List<Discipline>) ois.readObject();
                    ois.close();
                }
                catch (Exception e){}
                for(Discipline i:disciplineList){
                    if(i.getDisciplineName().equalsIgnoreCase(disciplineName)&&i.getTeacher().getName().equalsIgnoreCase(teacher)){
                        discipline = i;
                        validDiscipline = true;
                    }
                }
                if (!validDiscipline){
                    System.out.println("Invalid choice. Please try again");
                }
            }while (!validDiscipline);

            //select group from available groups in file groups.dat
            boolean validGroup;

            do{
                validGroup = false;
                System.out.println("Please select group for the lesson from following list:");
                FileReader fr = new FileReader(groups);
                BufferedReader br = new BufferedReader(fr);

                String s;
                while ((s = br.readLine()) != null){
                    System.out.println(s);
                }
                String groupName = in.nextLine();


                for (Group i:groupsList){
                    if(i.getGroupName().equalsIgnoreCase(groupName)){
                        group = i;
                        validGroup = true;
                    }
                }
                if (!validGroup){
                    System.out.println("Invalid choice. Please try again");
                }
            }while (!validGroup);

            //select type of class and add this class to schedule
            int choice = 0;
            do{
                System.out.println("Will this lesson be lecture(1) or practice(2)");
                choice=in.nextInt();
                in.nextLine();
                if (choice<1 || choice>2){
                    System.out.println("Invalid choice. Please try again");
                }
                else if(choice ==1){
                    try{
                        schedule.addLessonToSchedule(new Lecture(discipline, group, new LessonEvent(dayOfWeek, lessonNumber, building, room)));
                    }
                    catch (CannotAddToListException e){
                        System.out.println(e.getMessage());
                    }
                }
                else {
                    try{
                        schedule.addLessonToSchedule(new PracticalClass(discipline, group, new LessonEvent(dayOfWeek, lessonNumber, building, room)));
                    }
                    catch (CannotAddToListException e){
                        System.out.println(e.getMessage());
                    }
                }
            }while(choice<1 || choice>2);


            System.out.println("Do you wish to end building this schedule?(Y/N)");
            finishSchedule = in.nextLine();
        }while (!(finishSchedule.equalsIgnoreCase("y")));

        File scheduleFile = new File("schedule.dat");
        scheduleFile.createNewFile();

        FileReader fr = new FileReader(groups);
        BufferedReader br = new BufferedReader(fr);
        PrintWriter pw =new PrintWriter(scheduleFile);
        String s;
        while ((s = br.readLine()) != null){
            pw.print(s + "\t\t\t\t\t\t\t");
        }
        pw.print("\n");

        for(int i = Calendar.MONDAY; i<= Calendar.SATURDAY; i++){
            if (i == Calendar.MONDAY){
                pw.print("Monday:\n");
            }
            else if(i == Calendar.TUESDAY){
                pw.print("Tuesday:\n");
            }
            else if(i == Calendar.WEDNESDAY){
                pw.print("Wednesday:\n");
            }
            else if(i == Calendar.THURSDAY){
                pw.print("Thursday:\n");
            }
            else if(i == Calendar.FRIDAY){
                pw.print("Friday:\n");
            }
            else if(i == Calendar.SATURDAY){
                pw.print("Saturday:\n");
            }
            for(int j = 1; j <= 6; j++){
                pw.print(j + ". ");
                for (AuditoriumClass ac:schedule.getSchedule()){
                        if(ac.getTimeAndPlace().getLessonNumber()==j && ac.getTimeAndPlace().getDayOfWeek()==i){
                            for (Group g:groupsList){
                                if (g.equals(ac.getGroup())){
                                    if (ac.getDiscipline().getDisciplineName().length()>=28){
                                        pw.print("\t"+ac.getDiscipline().getDisciplineName());
                                    }
                                    if (ac.getDiscipline().getDisciplineName().length()>=24 && ac.getDiscipline().getDisciplineName().length()<28){
                                        pw.print("\t"+ac.getDiscipline().getDisciplineName()+"\t");
                                    }
                                    if (ac.getDiscipline().getDisciplineName().length()>=20 && ac.getDiscipline().getDisciplineName().length()<24){
                                        pw.print("\t"+ac.getDiscipline().getDisciplineName()+"\t\t");
                                    }
                                    if (ac.getDiscipline().getDisciplineName().length()>=16 && ac.getDiscipline().getDisciplineName().length()<20){
                                        pw.print("\t"+ac.getDiscipline().getDisciplineName()+"\t\t\t");
                                    }
                                    if (ac.getDiscipline().getDisciplineName().length()>=12 && ac.getDiscipline().getDisciplineName().length()<16){
                                        pw.print("\t"+ac.getDiscipline().getDisciplineName()+"\t\t\t\t");
                                    }
                                    if (ac.getDiscipline().getDisciplineName().length()>=8 && ac.getDiscipline().getDisciplineName().length()<12){
                                        pw.print("\t"+ac.getDiscipline().getDisciplineName()+"\t\t\t\t\t");
                                    }
                                    if (ac.getDiscipline().getDisciplineName().length()>=4 && ac.getDiscipline().getDisciplineName().length()<8){
                                        pw.print("\t"+ac.getDiscipline().getDisciplineName()+"\t\t\t\t\t\t");
                                    }
                                    if (ac.getDiscipline().getDisciplineName().length()>=0 && ac.getDiscipline().getDisciplineName().length()<4){
                                        pw.print("\t"+ac.getDiscipline().getDisciplineName()+"\t\t\t\t\t\t\t");
                                    }
                                }else{
                                    pw.print("\t\t\t\t\t\t\t\t");
                                }
                            }
                            pw.print("\n");
                            for (Group g:groupsList){
                                if (g.equals(ac.getGroup())){
                                    if (ac.getDiscipline().getTeacher().getName().length()>=28){
                                        pw.print("\t"+ac.getDiscipline().getTeacher().getName());
                                    }
                                    if (ac.getDiscipline().getTeacher().getName().length()>=24 && ac.getDiscipline().getTeacher().getName().length()<28){
                                        pw.print("\t"+ac.getDiscipline().getTeacher().getName()+"\t");
                                    }
                                    if (ac.getDiscipline().getTeacher().getName().length()>=20 && ac.getDiscipline().getTeacher().getName().length()<24){
                                        pw.print("\t"+ac.getDiscipline().getTeacher().getName()+"\t\t");
                                    }
                                    if (ac.getDiscipline().getTeacher().getName().length()>=16 && ac.getDiscipline().getTeacher().getName().length()<20){
                                        pw.print("\t"+ac.getDiscipline().getTeacher().getName()+"\t\t\t");
                                    }
                                    if (ac.getDiscipline().getTeacher().getName().length()>=12 && ac.getDiscipline().getTeacher().getName().length()<16){
                                        pw.print("\t"+ac.getDiscipline().getTeacher().getName()+"\t\t\t\t");
                                    }
                                    if (ac.getDiscipline().getTeacher().getName().length()>=8 && ac.getDiscipline().getTeacher().getName().length()<12){
                                        pw.print("\t"+ac.getDiscipline().getTeacher().getName()+"\t\t\t\t\t");
                                    }
                                    if (ac.getDiscipline().getTeacher().getName().length()>=4 && ac.getDiscipline().getTeacher().getName().length()<8){
                                        pw.print("\t"+ac.getDiscipline().getTeacher().getName()+"\t\t\t\t\t\t");
                                    }
                                    if (ac.getDiscipline().getTeacher().getName().length()>=0 && ac.getDiscipline().getTeacher().getName().length()<4){
                                        pw.print("\t"+ac.getDiscipline().getTeacher().getName()+"\t\t\t\t\t\t\t");
                                    }
                                }else{
                                    pw.print("\t\t\t\t\t\t\t\t");
                                }
                            }
                            pw.print("\n");
                            for (Group g:groupsList){
                                if(g.equals(ac.getGroup())){
                                    pw.print("\t"+"Building "+ac.getTimeAndPlace().getBuilding()+" Room "+ac.getTimeAndPlace().getRoom()+"\t\t\t");
                                }else{
                                    pw.print("\t\t\t\t\t\t\t\t");
                                }
                            }
                            pw.print("\n");
                            for (Group g:groupsList){
                                if(g.equals(ac.getGroup())){
                                    if(ac instanceof Lecture){
                                        pw.print("\tLecture\t\t\t\t\t\t");
                                    }
                                    else if (ac instanceof PracticalClass){
                                        pw.print("\tPractice\t\t\t\t\t");
                                    }
                                }else{
                                    pw.print("\t\t\t\t\t\t\t\t");
                                }
                            }
                        }
                }
                pw.print("\n");
            }
        }
        pw.flush();
        pw.close();
    }
}

